package com.github.editor.zip;


import com.github.editor.util.FileUtil;

import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class JavaZipUtil extends IZipUtil {

    @Override
    public void createNew(String srcPath, String dstPath, Map<String, String> updateList) throws IOException {
        //AndroidManifest.xml
        File outputFile = new File(dstPath);
        File dir = outputFile.getParentFile();
        if (dir != null) {
            if (dir.isFile()) {
                dir.delete();
            }
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
        if (outputFile.exists()) {
            outputFile.createNewFile();
        }
        if (dir != null && !dir.exists()) {
            throw new IOException("create dir error:" + dir.getAbsolutePath());
        }
        Map<String, ZipEntry> oldMap = new HashMap<>();
        try (ZipFile zipFile = new ZipFile(srcPath);
             FileOutputStream outputStream = new FileOutputStream(outputFile);
             ZipOutputStream zipArchiveOutputStream = new ZipOutputStream(outputStream)) {
            Enumeration<? extends ZipEntry> it =  zipFile.entries();
            while (it.hasMoreElements()) {
                ZipEntry old= it.nextElement();
                if (updateList.containsKey(old.getName())) {
                    oldMap.put(old.getName(), old);
                    continue;
                }
                ZipEntry newEntry = new ZipEntry(old.getName());
                newEntry.setMethod(old.getMethod());
                newEntry.setTime(old.getTime());
                if(old.getMethod() == ZipEntry.STORED){
                    newEntry.setCrc(old.getCrc());
                    newEntry.setSize(old.getSize());
                }
                zipArchiveOutputStream.putNextEntry(newEntry);
               // System.out.println(newEntry.getName() + ":" + newEntry.getMethod() + ",csize=" + newEntry.getCompressedSize() + ", size=" + newEntry.getSize());
                if (!old.isDirectory()) {
                    FileUtil.copy(zipFile.getInputStream(old), zipArchiveOutputStream);
                    //fixZipEntry(zipOutputStreamRef, newEntry);
                }
                zipArchiveOutputStream.closeEntry();
            }
            for (Map.Entry<String, String> item : updateList.entrySet()) {
                String entryName = item.getKey();
                String file = item.getValue();
                ZipEntry old = oldMap.get(entryName);
                //添加文件
                ZipEntry zipArchiveEntry = new ZipEntry(entryName);
                if (old != null) {
                    zipArchiveEntry.setMethod(old.getMethod());
                    zipArchiveEntry.setTime(old.getTime());
                } else {
                    zipArchiveEntry.setMethod(ZipEntry.DEFLATED);
                    zipArchiveEntry.setTime(347130062000L);
                }
                if (zipArchiveEntry.getMethod() == ZipEntry.STORED) {
                    zipArchiveEntry.setCrc(getCrc32(file));
                    zipArchiveEntry.setSize(new File(file).length());
                }
                zipArchiveOutputStream.putNextEntry(zipArchiveEntry);
                try (FileInputStream inputStream = new FileInputStream(file)) {
                    FileUtil.copy(inputStream, zipArchiveOutputStream);
                }
                zipArchiveOutputStream.closeEntry();
            }
        } catch (Exception e) {
            throw new IOException(e);
        }
    }

    @Override
    public void ReadZipEntry(String zip, String name, OutputStream outputStream) throws IOException {
        try (ZipFile zipFile = new ZipFile(zip)) {
            ZipEntry zipEntry = zipFile.getEntry(name);
            if (zipEntry == null) {
                throw new IOException("not found entry:" + name);
            }
            try (InputStream inputStream = zipFile.getInputStream(zipEntry);
            ) {
                FileUtil.copy(inputStream, outputStream);
            } catch (Throwable e) {
                //ignore
            }
        }
    }

    @Override
    public void exportFiles(String zip, String output, String... names) throws IOException {
        try (ZipFile zipFile = new ZipFile(zip)) {
            for (String name : names) {
                ZipEntry zipEntry = zipFile.getEntry(name);
                if (zipEntry == null) {
                    throw new IOException("not found entry:" + name);
                }
                File file = new File(output, name);
                File dir = file.getParentFile();
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                try (InputStream inputStream = zipFile.getInputStream(zipEntry);
                     FileOutputStream outputStream = new FileOutputStream(file);
                ) {
                    FileUtil.copy(inputStream, outputStream);
                } catch (Throwable e) {
                    //ignore
                }
            }
        }
    }

}
